function Financial(displayID) {
    var prefs = new gadgets.Prefs(),
	self = this;
    
    if (displayID) {
	this.displayID = displayID;
    }
    else {	//Use dummy ID.
	this.displayID = "preview";
    }

    this.allColumns = ["instrument", "customInstrument", "symbol", "lastPrice", "arrow", "change", "percentChange", "volume"];
    this.selectedColumns = [prefs.getString("column1"), prefs.getString("column2"), prefs.getString("column3"), prefs.getString("column4"),
	prefs.getString("column5"), prefs.getString("column6"), prefs.getString("column7")];
    this.numStocks = prefs.getInt("numStocks");
    this.showHeadings = prefs.getBool("showHeadings");
    this.autoScroll = prefs.getString("autoScroll");
    this.duration = prefs.getInt("duration") * 1000;
    this.condition1 = prefs.getInt("condition1");
    this.condition2 = prefs.getInt("condition2");
    this.condition3 = prefs.getInt("condition3");
    this.condition1Action = prefs.getString("condition1Action");
    this.condition2Action = prefs.getString("condition2Action");
    this.condition3Action = prefs.getString("condition3Action");
    this.backgroundColor = prefs.getString("backgroundColor");
    this.disclaimerFamily = prefs.getString("disclaimerFamily");
    this.layout = prefs.getString("layout");
    this.layoutURL = prefs.getString("layoutURL");
    
    if (prefs.getString("instruments")) {
	var instruments = prefs.getString("instruments").split(",");
	
	$.each(instruments, function(index, value) {
	    instruments[index] = $.trim(instruments[index]);
	});
	
	this.instruments = instruments.join("|");
    }
    else {
	this.instruments = "";
    }
    
    this.customInstruments = prefs.getString("customInstruments").split(",");
    
    if (this.layout == "logos") {
	this.layoutURL = "http://risegadgets.googlecode.com/svn/test/financial/logos.xml";
	this.allColumns.unshift("logo");
	this.selectedColumns.unshift("logo");
	
	//If conditions have been set, increase their value by 1 to account for the logo column.
	if (this.condition1 !== -1) {
	    this.condition1++;
	}
	
	if (this.condition2 !== -1) {
	    this.condition2++;
	}
	
	if (this.condition3 !== -1) {
	    this.condition3++;
	}
    }
    else if (this.layout == "noLogos") {
	this.layoutURL = "http://risegadgets.googlecode.com/svn/test/financial/noLogos.xml";
    }
    else {	//Custom
	if (!this.layoutURL) {	//No Layout URL specified.
	    this.layoutURL = "http://risegadgets.googlecode.com/svn/test/financial/logos.xml";
	}
	
	//TODO: Determine if custom layout has logo field.
	this.allColumns.unshift("logo");
	this.selectedColumns.unshift("logo");
    }
    
    this.updateInterval = 60000;
    this.checkForUpdates = false;
    this.isLoading = true;
    this.isPaused = true;
    this.logos = [];
    this.symbols = [];
    this.beforeValues = [];	//Will contain lastPrice, change, percentChange and volume.
    //The columns that some fields map to in the query.
    this.fieldNames = [];
    this.fieldNames["lastPrice"] = 2;
    this.fieldNames["change"] = 4;
    this.fieldNames["percentChange"] = 5;
    this.fieldNames["volume"] = 6;
    this.feedLoadFailedTimer = null;
}
//Load the layout and CSS.
Financial.prototype.loadLayout = function() {
    var params = {},
	self = this,
	link = $("<link>");
     
    if (this.layoutURL) {
	params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.DOM;	
	gadgets.io.makeRequest(this.layoutURL, function(obj) {
	    var data = obj.data;
	    
	    if (data.getElementsByTagName("Style").length > 0) {
		var head = document.getElementsByTagName("head")[0],
		    style = document.createElement("style");
		    
		style.type = "text/css";
		style.innerHTML = data.getElementsByTagName("Style")[0].childNodes[1].nodeValue;
		head.appendChild(style);
	    }
	    
	    if (data.getElementsByTagName("Layout").length == 0) {
		return;
	    }
	    
	    //Set the layout for the first page.
	    self.layout = data.getElementsByTagName("Layout")[0].childNodes[1].nodeValue;
	    self.getStocks();
	}, params);
    }
}
Financial.prototype.getStocks = function() {
    var limit = "";
    
    this.logoCount = 0;
    
    if (this.numStocks) {
	limit = " LIMIT " + this.numStocks;
    }
    
    var self = this,
	settings = {
	    url: "http://financial.risedisplay.com/gv/stocks?codes=" + this.instruments + "&id=" + this.displayID,
	    //url: "http://contentfinancial-test.appspot.com/gv/stocks?codes=" + this.instruments + "&id=" + this.displayID,
	    refreshInterval: 0,	//Can't get refreshInterval to work, so don't use it.
	    queryString: "select DSPLY_NAME, RIC, TRDPRC_1, PRCTCK_1, NETCHNG_1, PCTCHNG, ACVOL_1 ORDER BY TRDPRC_1 desc" + limit,	//Instrument Name, Instrument (Symbol), Last Price, Tick, Net Change, Percent Change, Accumulated Volume
	    callback: function(data) {
		clearTimeout(self.feedLoadFailedTimer);
		
		//This is a chain and a request for a chain cannot be combined with a request for individual stocks.
		//So if the Instrument Name of the first row is INCORRECT_TYPE, the instrument must be a chain.
		if (data.getFormattedValue(0, 0) == "INCORRECT_TYPE") {
		    self.getChains();
		}
		else {
		    self.data = data;
		    self.getSymbols();
		    
		    if (self.layout == "noLogos") {
			self.showStocks();
		    }
		    else {
			self.getLogoURLs();
		    }
		}
	    }
	};
    
    //Start a timer in case there is a problem loading the feed (i.e. Internet has been disconnected).
    this.feedLoadFailedTimer = setTimeout(function() {
	self.getStocks();
    }, this.updateInterval);
    
    getRawData(settings);
}
Financial.prototype.getChains = function() {
    var limit = "";
    
    if (this.numStocks) {
	limit = " LIMIT " + this.numStocks;
    }
    
    var self = this,
	settings = {
	    url: "http://financial.risedisplay.com/gv/chain?code=" + this.instruments + "&id=" + this.displayID,
	    //url: "http://contentfinancial-test.appspot.com/gv/chain?code=" + this.instruments + "&id=" + this.displayID,
	    refreshInterval: 0,
	    queryString: "select DSPLY_NAME, RIC, TRDPRC_1, PRCTCK_1, NETCHNG_1, PCTCHNG, ACVOL_1 ORDER BY TRDPRC_1 desc" + limit,	//Instrument Name, Instrument (Symbol), Last Price, Tick, Net Change, Percent Change, Accumulated Volume
	    callback: function(data) {
		clearTimeout(self.feedLoadFailedTimer);
		
		self.data = data;
		self.getSymbols();
		
		if (self.layout == "noLogos") {
		    self.showStocks();
		}
		else {
		    self.getLogoURLs();
		}
	    }
	};
	
    //Start a timer in case there is a problem loading the feed (i.e. Internet has been disconnected).
    this.feedLoadFailedTimer = setTimeout(function() {
	self.getChains();
    }, this.updateInterval);
    
    getRawData(settings);
}
Financial.prototype.getSymbols = function() {
    for (var row = 0, numRows = this.data.getNumberOfRows(); row < numRows; row++) {
	this.symbols[row] = this.data.getFormattedValue(row, 1);
    }
}
Financial.prototype.getLogoURLs = function() {
    var queryString = "select C, D";
    
    for (var i = 0; i < this.symbols.length; i++) {
	if (i == 0) {
	    queryString += " where C = '" + this.symbols[i] + "'";
	}
	else {
	    queryString += " or C = '" + this.symbols[i] + "'";
	}
    }
    
    var self = this,
	logoSettings = {
	    url: "https://docs.google.com/a/risevision.com/spreadsheet/tq?key=0AnsiFJce3EYCdHA5NWp2VVVxV1pZUFFHMmpiUGx1TXc&headers=1",
	    refreshInterval: 0,
	    queryString: queryString,
	    callback: function(data) {
		//No logos found. Hide the column.
		if (data.getNumberOfRows() == 0) {
		    $(".logo").hide();
		    $(".logoContainer").hide();
		}
		else {
		    for (var row = 0, numRows = data.getNumberOfRows(); row < numRows; row++) {
			self.logos[row] = {
			    symbol: data.getValue(row, 0),
			    url: data.getValue(row, 1)
			};
		    }
		    
		    $(".logo").show();
		    $(".logoContainer").show();
		}
		
		if (self.logos.length > 0) {
		    self.loadLogos();
		}
		else {
		    self.showStocks();
		}
	    }
	};
	
    getRawData(logoSettings);
}
Financial.prototype.loadLogos = function() {
    var self = this,
	upArrow = new Image(),
	downArrow = new Image();
    
    //Load arrows.
    upArrow.src = "http://risegadgets.googlecode.com/svn/test/financial/up-arrow.gif";
    downArrow.src = "http://risegadgets.googlecode.com/svn/test/financial/down-arrow.gif";
    
    //Load all company logos.
    $.each(this.logos, function(index, value) {
	var img = new Image();
	
	img.onload = function () {
	    self.logoCount++;
	    self.onImageLoaded();
	}
	
	img.onerror = function() {
	    self.logoCount++;
	    self.onImageLoaded();
	}
	
	img.src = value.url;
    });    
}
Financial.prototype.onImageLoaded = function() {
    if (this.logoCount >= this.logos.length) {
	this.showStocks();
    }
}
Financial.prototype.showStocks = function() {
    var self = this;
    
    $("#container").empty();
    $("#container").append(self.layout);
    
    for (var row = 0, numRows = this.data.getNumberOfRows(); row < numRows; row++) {
	this.addRow(row);
    }
    
    //Add headings last, after we know what the width of each cell should be as determined by the data.	    	    
    //Give the row a class that we can use for distinguishing between them when handling conditions.
    //The class name will be the same as the instrument's symbol.
    for (var j = 0; j < this.symbols.length; j++) {
	$("#data").find(".item").eq(j).addClass(this.symbols[j].replace(".", ""));
    }
    
    //Configure disclaimer.
    $("#disclaimer").text("Market Data by Thomson Reuters - Delayed 20 Minutes");
    $("#disclaimer").css("font-family", this.disclaimerFamily);
    $("#disclaimer").css("background-color", this.backgroundColor);
	
    if (this.showHeadings) {
	$("#headings").width($("#data").width());
	
	if (this.backgroundColor) {
	    $("#headings").css("background-color", this.backgroundColor);
	}
	
	for (var i = 0; i < this.allColumns.length; i++) {
	    var columnFound = false;
    
	    //Remove any headings from the layout that have not been selected to display.
	    for (var j = 0; j < this.selectedColumns.length; j++) {
		if (this.allColumns[i] == this.selectedColumns[j]) {
		    columnFound = true;
		    break;
		}
	    }
	    
	    if (!columnFound) {
		$("#headings ." + this.allColumns[i]).remove();
	    }
	}
	
	$("#headings th").each(function(index) {
	    if ($(this).css("display") != "none") {
		$(this).width($(".item > td").eq(index).outerWidth());
	    }
	});

	$("#scrollContainer").height($("#container").height() - $("#headings").outerHeight(true) - $("#disclaimer").outerHeight(true));
    }
    else {
	$("#headings").hide();
    }
    
    
    this.handleConditions();
    
    if (this.autoScroll !== "none") {
	$("#scrollContainer").infiniteScroll({
	    scrollBy: this.autoScroll,
	    duration: this.duration
	})
	.bind("onScroll", function(event) {
	    self.onScroll.call(self, event);
	});
	
	if (!this.isLoading) {
	    if (this.autoScroll === "page") {
		//Scroll to first instance of row with the given class.
		var success = $("#scrollContainer").infiniteScroll.scrollToClass(this.firstClass);
		
		//Scroll to row with the given position.
		if (!success) {
		    var className = this.getItemClassByPosition();
		    
		    if (className) {
			$("#scrollContainer").infiniteScroll.scrollToClass(className, false);
		    }
		}
	    }
	
	    if (!this.isPaused) {
		$("#scrollContainer").infiniteScroll.start();
	    }
	}
    }
    
    this.isLoading = false;
    readyEvent();
    
    setTimeout(function() {
	//If we're not scrolling, or there is not enough content to scroll, check for updates right away.
	if ((self.autoScroll === "none") || (!$("#scrollContainer").infiniteScroll.canScroll())) {
	    self.getStocks();
	}
	else {
	    self.checkForUpdates = true;
	}
    }, this.updateInterval);
}
Financial.prototype.addRow = function(row) {
    var $item,
	self = this;
    
    //Customize DOM elements for first item. All subsequent items will clone this one.
    if (row === 0) {
	var $heading = $(".heading:not(.logo)"),
	    $value = $(".value:not(.logo)"),
	    isFirst = true;
	
	//Add HTML elements for each selected column that is not "none" or the logo.
	$.each(this.selectedColumns, function(index, value) {
	    if (value != "none" && value != "logo") {
		//Clone the column for all except the first one.
		if (!isFirst) {
		    $heading.parent().append($heading.clone());
		    $value.parent().append($value.clone());
		}
		else {
		    isFirst = false;
		}
	    }
	});
	
	var headingIndex = 0;
	var valueIndex = 0;
	
	//All headings have been added, now customize them.
	$.each(this.selectedColumns, function(index, value) {
	    var $headings =  $(".heading:not(.logo)")
		$values = $(".value:not(.logo)");
	    
	    if (value != "none" && value != "logo") {
		var $heading = $headings.eq(headingIndex),
		    $value = $values.eq(valueIndex);
		    
		$heading.addClass(self.selectedColumns[index]);
		$value.addClass(self.selectedColumns[index]);
		    
		if (self.selectedColumns[index] == "lastPrice") {
		    $heading.text("Last");
		    $value.addClass("numeric");
		}
		else if (self.selectedColumns[index] == "change") {
		    $heading.text("Change");
		    $value.addClass("numeric");
		}
		else if (self.selectedColumns[index] == "percentChange") {
		    $heading.text("% Change");
		    $value.addClass("numeric");
		}
		else if (self.selectedColumns[index] == "volume") {
		    $heading.text("Accumulated Volume");
		    $value.addClass("numeric");
		}
		
		headingIndex++;
		valueIndex++;
	    }
	});
	
	$item = $("#data").find(".item:last");
    }
    //Append a new item to the DOM.
    else {
	$(".item").parent().append($(".item:last").clone());
	
	//If scrolling, add 'last' class to last item so doneEvent can be called when the last item has scrolled.
	if (row === this.data.getNumberOfRows() - 1 && this.autoScroll !== "none") {
	    $(".item:last").addClass("last");
	}
    }
    
    $item = $("#data").find(".item:last");
    
    for (var i = 0; i < this.allColumns.length; i++) {
	var columnFound = false;
	
	for (var j = 0; j < this.selectedColumns.length; j++) {
	    if (this.allColumns[i] == this.selectedColumns[j]) {
		columnFound = true;
		break;
	    }
	}
	
	if (columnFound) {
	    var $field;
	    
	    switch(this.selectedColumns[j]) {
		case "logo":
		    var logoFound = false, j = 0;
		    
		    $field = $item.find(".logo");
		    
		    for (j = 0; j < this.logos.length; j++) {
			if (this.logos[j].symbol == this.symbols[row]) {
			    logoFound = true;
			    break;
			}
		    }
		    
		    if (logoFound) {
			$field.css("background-image", "url(" + this.logos[j].url + ")");
		    }
		    else {
			$field.css("background-image", "");
		    }
		    
		    break;
		case "instrument":
		    $field = $item.find(".instrument");
		    $field.text(this.data.getFormattedValue(row, 0));
		    
		    break;
		case "customInstrument":
		    $field = $item.find(".customInstrument");
		    
		    if (this.customInstruments[row]) {
			$field.text(this.customInstruments[row]);	
		    }
		    else {
			$field.text("");
		    }
		    
		    break;
		case "symbol":
		    $field = $item.find(".symbol");
		    $field.text(this.symbols[row]);
		    break;
		case "lastPrice":
		    $field = $item.find(".lastPrice");
		    $field.text(this.addCommas(parseFloat(this.data.getFormattedValue(row, 2)).toFixed(2)));
		    break;
		case "arrow":
		    var $div;
		    
		    $field = $item.find(".arrow");
		    $field.text("");
		    
		    //No image element exists (i.e. this is the first row of data). Create one and append it to the DOM.
		    if ($item.find(".arrow div").length == 0) {
			$div = $("<div>");
			$field.append($div);
		    }
		    else {
			$div = $item.find(".arrow div");
		    }
		    
		    if (this.data.getFormattedValue(row, 3) == "U") {	//Up
			$div.css("background-image", "url(http://risegadgets.googlecode.com/svn/test/financial/up-arrow.gif)");
		    }
		    else if (this.data.getFormattedValue(row, 3) == "D") {
			$div.css("background-image", "url(http://risegadgets.googlecode.com/svn/test/financial/down-arrow.gif)");
		    }
		    else {	//N/P
		    	$field.text(this.data.getFormattedValue(row, 3));
		    }
		    
		    break;
		case "change":
		    $field = $item.find(".change");
		    $field.text(parseFloat(this.data.getFormattedValue(row, 4)).toFixed(2));
		    break;
		case "percentChange":
		    $field = $item.find(".percentChange");
		    $field.text(parseFloat(this.data.getFormattedValue(row, 5)).toFixed(2) + "%");
		    break;
		case "volume":
		    $field = $item.find(".volume");
		    $field.text(this.addCommas(parseFloat(this.data.getFormattedValue(row, 6))));
		    break;
		default:	//none
	    }
	}
	else {	//Column not selected. Remove from DOM.
	    $item.find("." + this.allColumns[i]).remove();
	}
    }
}
Financial.prototype.onScroll = function(e) {
    var self = this;
    
    if (this.autoScroll === "item") {
	//Scroll off last item, then move to next playlist item, if applicable.
	if ($(".item:last").hasClass("last")) {
	    if (self.checkForUpdates) {
		self.checkForUpdates = false;
		self.getStocks();
	    }
	    
	    doneEvent();
	}
    }
    else if (this.autoScroll === "page") {
	//Scroll off page containing last item, then move to next playlist item, if applicable.
	if (this.isItemVisible($(".last:first"))) {
	    setTimeout(function() {
		if (self.checkForUpdates) {
		    //Remember the class of the first item, as well as its position relative to the last item.
		    //After refreshing, we will scroll to the first item with that class or, if it doesn't exist, we will scroll to the
		    //item in that position.
		    self.getFirstItemClass();
		    self.positionFromLast = $(".last:first").prevAll().length - 1;
		    self.checkForUpdates = false;
		    self.getStocks();
		}
	    
		doneEvent();
	    }, this.duration);
	}
    }
}
//Before updating, remember which item is at the top so we can show it at the top again after refreshing the data.
//Count how many items away from the last one we are. We can't rely on the symbol class because it might no longer
//be a part of the chain when refreshed.
Financial.prototype.getFirstItemClass = function() {
    var $firstItem = $(".item:first"),
	classes = $firstItem.attr("class").split(" ");
    
    for (var i = 0; i < classes.length; i++) {
	if (classes[i] !== "item") {
	    this.firstClass = classes[i];
	    break;
	}
    }
}

Financial.prototype.getItemClassByPosition = function() {
    var $prevAll = $(".last:first").prevAll(), $item, className;
		
    if ($prevAll.eq(this.positionFromLast).length !== 0) {	//Item exists at this position.
	$item = $prevAll.eq(this.positionFromLast);
    }
    else {	//No item found at this position because some items have been removed.
    }
    
    if ($item) {
	var classes = $item.attr("class").split(" ");
	
	//Get class of this item and scroll to it.
	for (var i = 0; i < classes.length; i++) {
	   if (classes[i] !== "item") {
		className = classes[i];
		break;
	   }
	}
    }
    
    return className;
}

Financial.prototype.addCommas = function(number)
{
    number += '';
    var x = number.split('.');
    var x1 = x[0];
    var x2 = x.length > 1 ? '.' + x[1] : '';
    var regex = /(\d+)(\d{3})/;
    
    while (regex.test(x1)) {
	x1 = x1.replace(regex, '$1' + ',' + '$2');
    }
    
    return x1 + x2;
}
Financial.prototype.isItemVisible = function($item) {
    if (($item.outerHeight(true) + $item.position().top) <= $("#scrollContainer").outerHeight(true)) {
	return true;
    }
    else {
	return false;
    }
}
Financial.prototype.play = function() {
    if (this.autoScroll === "none") {
	setTimeout(function() {
	    doneEvent();
	}, this.duration);
    }
    else {
	if ($("#scrollContainer").infiniteScroll.canScroll()) {
	    if (this.isPaused) {
		$("#scrollContainer").infiniteScroll.start();
		this.isPaused = false;
	    }
	}
	else {
	    setTimeout(function() {
		doneEvent();
	    }, this.duration);
	}
    }
}
Financial.prototype.pause = function () {
    if (this.autoScroll !== "none") {
	$("#scrollContainer").infiniteScroll.pause();
	this.isPaused = true;
    }
}
Financial.prototype.handleConditions = function() {    
    if (!this.conditions) {	//On initial load.
	this.conditions = {};
    }
    
    if (this.condition1 != -1) {
	if (this.condition1Action == "valuePositive" || this.condition1Action == "valueNegative") {
	    this.checkSigns(this.condition1Action, this.condition1);
	}
	else {
	    if (this.conditions.condition1) {
		this.checkConditions(this.conditions.condition1, this.condition1Action, this.condition1);
	    }
	}
    }
    
    if (this.condition2 != -1) {
	if (this.condition2Action == "valuePositive" || this.condition2Action == "valueNegative") {
	    this.checkSigns(this.condition2Action, this.condition2);
	}
	else {
	    if (this.conditions.condition2) {
		this.checkConditions(this.conditions.condition2, this.condition2Action, this.condition2);
	    }
	}
    }
    
    if (this.condition3 != -1) {
	if (this.condition3Action == "valuePositive" || this.condition3Action == "valueNegative") {
	    this.checkSigns(this.condition3Action, this.condition3);
	}
	else {
	    if (this.conditions.condition3) {
		this.checkConditions(this.conditions.condition3, this.condition3Action, this.condition3);
	    }
	}
    }

    this.saveConditions();
}
Financial.prototype.checkSigns = function(action, conditionIndex) {
    var column = this.fieldNames[this.selectedColumns[conditionIndex]];
    
    //If column is undefined, then this is not a numeric column.
    if (column) {
	for (var row = 0, numRows = this.data.getNumberOfRows(); row < numRows; row++) {
	    var current = this.data.getValue(row, column),	//new value from data source.
		symbol = this.data.getFormattedValue(row, 1),
		$rows = $("#data").find("." + symbol.replace(".", ""));    
    
	    //Handle each row. There may be more than one in the case of scrolling by page.
	    $rows.each(function(index) {
		var $value = $(this).find(".value").eq(conditionIndex);	//This will be incorrect if any column is none before the condition column.
		
		if (isNaN(current)) {
		    current = current.replace(/[^0-9\.-]+/g,"");
		    current = parseFloat(current);
		}
		
		//Clear any previous condition classes.
		$value.removeClass("valuePositivePositive valuePositiveNegative valueNegativeNegative valueNegativePositive");
	
		if (!isNaN(current)) {
		    if (action == "valuePositive") {
			if (current >= 0) {
			    $value.addClass("valuePositivePositive");
			}
			else {
			    $value.addClass("valuePositiveNegative");
			}
		    }
		    else {
			if (current < 0) {
			    $value.addClass("valueNegativeNegative");
			}
			else {
			    $value.addClass("valueNegativePositive");
			}
		    }
		}
	    });
	}
    }
}
//Compare new values to old one's.
Financial.prototype.checkConditions = function(condition, action, conditionIndex) {
    var column = this.fieldNames[this.selectedColumns[conditionIndex]];
    
    //If column is undefined, then this is not a numeric column.
    if (column) {
	for (var row = 0, numRows = this.data.getNumberOfRows(); row < numRows; row++) {
	    var current = this.data.getValue(row, column),
		previous = condition[row],
		symbol = this.data.getFormattedValue(row, 1),
		$rows = $("#data").find("." + symbol.replace(".", ""));
		
	    //Handle each row. There may be more than one in the case of scrolling by page.
	    $rows.each(function(index) {
		var $value = $(this).find(".value").eq(conditionIndex);
    
		if (isNaN(current)) {
		    current = current.replace(/[^0-9\.-]+/g,"");
		    current = parseFloat(current);
		}
		
		if (isNaN(previous)) {
		    previous = previous.replace(/[^0-9\.-]+/g,"");
		    previous = parseFloat(previous);
		}
	
		//The data type of a column can still be a number even if there is string data in it.
		//To be sure, let's check that the values we are comparing are numbers.
		if (current != previous && !isNaN(current) && !isNaN(previous)) {
		    //Clear any previous condition classes.
		    $value.removeClass("changeUpIncrease changeUpDecrease changeDownDecrease changeDownIncrease");
		
		    if (action == "changeUp") {
			if (current > previous) {
			    $value.addClass("changeUpIncrease");
			}
			else {
			    $value.addClass("changeUpDecrease");
			}
		    }
		    else {
			if (current < previous) {
			    $value.addClass("changeDownDecrease");
			}
			else {
			    $value.addClass("changeDownIncrease");
			}
		    }
		}
	    });
	}
    }
}
Financial.prototype.saveConditions = function() {
    if (this.condition1 != -1) {
	this.conditions.condition1 = [];
	this.saveCondition(this.conditions.condition1, this.condition1);
    }
    
    if (this.condition2 != -1) {
	this.conditions.condition2 = [];
	this.saveCondition(this.conditions.condition2, this.condition2);
    }
    
    if (this.condition3 != -1) {
	this.conditions.condition3 = [];
	this.saveCondition(this.conditions.condition3, this.condition3);
    }
}
//Store the current values so they can be compared to new values on a refresh.
Financial.prototype.saveCondition = function(condition, conditionIndex) {
    var column = this.fieldNames[this.selectedColumns[conditionIndex]];
    
    if (column) {
	for (var row = 0, numRows = this.data.getNumberOfRows(); row < numRows; row++) {
	    condition.push(this.data.getValue(row, column));
	}
    }
}